package cz.tpj.upl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javazoom.upload.MultipartFormDataRequest;
import javazoom.upload.UploadBean;
import cz.tpj.database.obrazky.Obrazok;
import cz.tpj.database.obrazky.Table_picture;
import cz.tpj.database.obrazok_mesto.Table_CityPictures;
import cz.tpj.logic.Navigation;
import cz.tpj.util.ErrorClass;
import cz.tpj.util.ErrorDatabase;

/**
 * Trida typu singelton. Pracuje s obrazky at uz v tempu a nebo primo ve slozkach. Ma synchronizovane metody,
 * aby se udrzela konzistence a neprepisoval se napriklad tem soucasne vice uzivateli
 * @author Martin
 *
 */
public class MediaFolder {
	private static MediaFolder IM = null;
	
	private MediaFolder(){}
	
	/**
	 * Vraci instanci teto tridy
	 * @return
	 */
	public static MediaFolder getInstance(){
		if(IM == null){
			IM = new MediaFolder();
		}
		return IM;
	}
	
	/**
	 * Uploadovane soubory ulozi do tempu. Predesle soubory z tempu odstrani
	 * @param request
	 * @param response
	 * @throws ErrorClass
	 */
	public synchronized void uploadFile(HttpServletRequest request, HttpServletResponse response) throws ErrorClass{
		//kontrola, zda se jedna o: ENCTYPE="multipart/form-data"
		if (MultipartFormDataRequest.isMultipartFormData(request)) {
			try {
				//slozka kam se prozatimne budou ukladat upladovene soubory (obrazky)
				File folder = new File(Navigation.MEDIA_FOLDER_TEMP);
				//smazani starych soboru
				if(folder.exists()){
					//nacte vsecky cojsou v te slozce
					String[] files = folder.list();
					//a jeden po druhem vymaze
					for(int i = 0; i < files.length; i++){
						File f = new File(Navigation.MEDIA_FOLDER_TEMP + files[i]);
						f.delete();
					}
				}
				// zkontroluje, jestli slozka neexistuje a pokud neexistuje, pak ji vytvori
				if (!folder.exists() && !folder.mkdirs()) {
					//v pripade, ze neexistovala a zaroven nesla vytvorit vyhod vyjumku
					throw new ErrorClass(ErrorClass.INTERNAL_ERROR_SAVE_DATA_ON_SERVER);
				}
				//---samotne nacteni a ulozenisouboru---
				int uploadlimit = 1024*1024*1024; // 1GB
		        String parser = MultipartFormDataRequest.COSPARSER;
		        String encoding = "UTF-8";
		        MultipartFormDataRequest mrequest = new MultipartFormDataRequest(request, null, uploadlimit, parser, encoding);
		        // UploadBean initialization (scope = request).
		        UploadBean upBean = new UploadBean();
		        // Select the folder to upload files (for database or Zip, see documentation)
		        upBean.setFolderstore(folder.getAbsolutePath());
		        upBean.store(mrequest);
		        //---------------------------------------
			}catch (Exception e) {
				throw new ErrorClass(ErrorClass.INTERNAL_ERROR_SAVE_DATA_ON_SERVER);
			}
		}else{
			throw new ErrorClass(ErrorClass.INVALID_DATA_FORMAT, "Na server byla data zaslana v neznamem formatu/formulari");
		}
	}//---uploadFile()---
	
	/**
	 * @throws ErrorClass 
	 * @throws ErrorDatabase 
	 * 
	 */
	public synchronized String moveImagesInMediaFolder(String cityID) throws ErrorClass, ErrorDatabase{
		String message = new String();
		//slozky tem a cities
		File sourceFolder = new File(Navigation.MEDIA_FOLDER_TEMP);
		File destinationFolder = new File(Navigation.MEDIA_FOLDER_CITIES + cityID + "/");
		//vytvoreni slozky do ktere se budou data kopirovat
		try {
			// zkontroluje, jestli slozka neexistuje a pokud neexistuje, pak ji vytvori
			if (!destinationFolder.exists() && !destinationFolder.mkdirs()) {
				//v pripade, ze neexistovala a zaroven nesla vytvorit vyhod vyjumku
				throw new ErrorClass(ErrorClass.INTERNAL_ERROR_SAVE_DATA_ON_SERVER);
			}
		} catch (Exception e) {
			throw new ErrorClass(ErrorClass.INTERNAL_ERROR_SAVE_DATA_ON_SERVER);
		}
		//vlastni kopirovani jednotlivych souboru
		if (sourceFolder.isDirectory() && destinationFolder.isDirectory()) {
			//nacti vsechny soubory do pole
			File[] files = sourceFolder.listFiles();
			String sourceFile, destinationFile;
			//vem z pole files sobor a presun ho. Opakovat dokud jsou nejake sobory ve files
			for(int i =0; i<files.length; i++){
				//nacte jmeno zdrojoveho souboru
				sourceFile = files[i].getName();
				//vytvori jmeno ciloveho souboru
				destinationFile = destinationFolder.getAbsolutePath() + "/" + sourceFile;
				//presune metodou files(z, do) ... (v pripade selhani vraci chybu)
				message += moveFile(files[i], new File(destinationFile));
				//aktualizuj databazi 
				updateDatabaze(cityID, sourceFile);
			}
		}
		return message;
	}

	private void updateDatabaze(String cityID, String destinationFile) throws ErrorDatabase {
		//instance zkopirovaneho souboru s obrazkem
		Obrazok picture = new Obrazok();
		picture.setCesta(cityID + "/" +destinationFile);
		//prida polozku do tabulky obrazek
		String imageID = Table_picture.getInstance().insertPicture(picture);
		//priradi obrazek k mestu v tabulce obrazek_mesto 
		Table_CityPictures.getInstance().addPictureToCity(cityID, imageID);
	}

	public String moveFile(File from, File to) {
		String message = new String();
		FileInputStream input = null;
		FileOutputStream output = null;
		try {
			//vytvori novoy soubor, pokud se nepodari, pak vyvola vyjimku
			if(!to.exists() && !to.createNewFile()){
				throw new IOException();
			}
			//otevri vstupni a vystupni soubory
			input = new FileInputStream(from);
			output = new FileOutputStream(to);
			//kopirovani dat
			byte data[] = new byte[1024];
			int cout;
			while (input.available() > 0) {
				cout = input.read(data);
				output.write(data, 0, cout);
			}
		} catch (IOException e) {
			message = "Chyba při kopírování souboru: " + from.getName() + "<br>";
		} finally {
			try {
				input.close();
				output.close();
			} catch (IOException e) {}
		}
		
		
		return message;
	}

	
	
	
}
